package com.example.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.service.*;
import com.example.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @description: 积分商品兑换订单
 */
@RestController
@RequestMapping("creditsOrder")
public class CreditsOrderController {

    @Autowired
    private CreditsOrderService service;

    @Autowired
    private GetCreditsService getCredits;

    @Autowired
    private CreditsShopsService creditsShopsService;

    @Autowired
    private UserService userService;

    @Autowired
    @Lazy
    private CreditsOrderController creditsOrder;

    // 库存加锁 防止库存被超卖
    Lock lock = new ReentrantLock();

    /**
     * @param json
     * @description: 分页
     * @return: com.example.common.entity.Result
     * @author: xxx
     * @time: 2021/7/19 09:30
     */
    @RequestMapping("getPage")
    public Result getPage(@RequestBody String json) {

        JSONObject jsonObject = JSON.parseObject(json);
        Page.getPage(jsonObject);
        List<Map<String, Object>> list = service.getList(jsonObject);
        int total = service.getCount(jsonObject);

        return ResultUtil.successPage(list, total);
    }

    /**
     * @param json
     * @description: 列表
     * @return: com.example.common.entity.Result
     * @author: xxx
     * @time: 2021/5/06 09:30
     */
    @RequestMapping("getList")
    public Result getList(@RequestBody String json) {
        JSONObject jsonObject = JSON.parseObject(json);
        List<Map<String, Object>> list = service.getList(jsonObject);
        return ResultUtil.success(list);
    }

    /**
     * @param map
     * @description: 详情
     * @return: com.example.common.entity.Result
     * @author: xxx
     * @time: 2021/5/06 09:30
     */
    @RequestMapping("getById")
    public Result getById(@RequestBody Map<String, Object> map) {

        return ResultUtil.success(service.getById(map));
    }

    /**
     * @param map
     * @description: 兑换生成订单
     * @return: com.example.common.entity.Result
     * @author: xxx
     * @time: 2021/5/06 09:30
     */
    @RequestMapping("save")
    public Result save(@RequestBody Map<String, Object> map) throws Exception {
        // 当前方法加锁
        lock.lock();
        try {
            // 获取用户积分
            Map<String, Object> params = new HashMap();
            params.put("id", TokenTool.getUserId());
            Map<String, Object> UserCredits = getCredits.getMyCredits(params);
            // 获取商品信息 以及商品价值
            Map<String, Object> shopdetails = new HashMap();
            shopdetails.put("id", map.get("shopId"));
            Map<String, Object> ShopDetails = creditsShopsService.getById(shopdetails);
            Integer surpusStock = (Integer) ShopDetails.get("surplusStock");
            // 如果库存为0直接拜拜
            if (surpusStock > 0) {
                // 如果积分不够
                Double total = (Double) UserCredits.get("total");
                Integer creditPrice = (Integer) ShopDetails.get("creditPrice");
                // 用户的可用积分 < 商品价值积分
                if (total != null && creditPrice != null) {
                    if (total < creditPrice) {
                        // 积分不够
                        return ResultUtil.error(-500, "您的积分不足~");
                    } else {
                        creditsOrder.addOrderAndCredits(map, surpusStock, ShopDetails, total);
                        return ResultUtil.success();
                    }
                } else {
                    // 获取用户积分或者获取商品价格积分失败
                    return ResultUtil.error(-500, "商品太火爆~");
                }
            } else {
                return ResultUtil.error(-500, "该商品已被抢光~");
            }

        } catch (Exception e) {
           // throw new Exception("该商品太火爆了~");
           return ResultUtil.error(-500, "商品太火爆了~");
        } finally {
            // 解锁
            lock.unlock();
        }
    }

    // 兑换具体方法 (事务模式)
    @Transactional(rollbackFor = Exception.class)
    public void addOrderAndCredits(Map<String, Object> map, Integer surpusStock, Map<String, Object> ShopDetails, Double total) {
        // total 大于 或等于 creditPrice 都可以兑换
        // 获取用户信息
        Map<String, Object> userMap = new HashMap();
        userMap.put("id", TokenTool.getUserId());
        Map<String, Object> userInfo = userService.getById(userMap);

        // 兑换逻辑
        // 1. 减少商品库存
        Map<String, Object> shopkc = new HashMap();
        surpusStock = surpusStock - 1;
        shopkc.put("id", map.get("shopId"));
        shopkc.put("surplusStock", surpusStock);
        creditsShopsService.update(shopkc);

        // 2. 生成积分订单
        Map<String, Object> orderMap = new HashMap();
        orderMap.put("id", IDTool.getUUID32()); // id标识
        orderMap.put("shopId", map.get("shopId")); // 商品id
        orderMap.put("userId", userInfo.get("id")); // 用户id
        orderMap.put("shopSn", ShopDetails.get("goodsSn")); // 商品编号
        orderMap.put("userName", userInfo.get("name")); // 用户账号
        orderMap.put("userNickname", userInfo.get("nikeName")); // 用户账号
        orderMap.put("remark", map.get("remark")); // 备注
        orderMap.put("addressId", map.get("addressId")); // 地址id
        orderMap.put("shopImage", ShopDetails.get("goodsImage")); // 商品图
        orderMap.put("shopName", ShopDetails.get("goodsName")); // 商品名
        orderMap.put("shopCreditsPrice", ShopDetails.get("creditPrice"));  // 所需积分
        orderMap.put("added", 1);  // 提交订单，需要审核
        // 生成订单编号
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        String DataSn = simpleDateFormat.format(new Date());
        orderMap.put("orderSn", DataSn);
        service.save(orderMap);

        // 3. 扣除用户积分--插入到积分表里
        // 计算剩余积分 账户积分 - 商品积分
        BigDecimal totalC = new BigDecimal(Double.valueOf(total.toString()));  // 账户目前可用积分 total
        BigDecimal gCredit = new BigDecimal(Double.valueOf(ShopDetails.get("creditPrice").toString()));// 此单消耗积分金额
        BigDecimal tdMoney = totalC.subtract(gCredit).setScale(2, BigDecimal.ROUND_HALF_UP);// 减法四舍五入保留两位小数
        // 3.1 兑换商品消耗积分的参数
        Map<String, Object> creditAdd = new HashMap();
        creditAdd.put("id", IDTool.getUUID32()); // 参数id
        creditAdd.put("userId", userInfo.get("id")); // 用户id
        creditAdd.put("userPhone", userInfo.get("name")); // 用户手机号
        creditAdd.put("userName", userInfo.get("nikeName")); // 用户手机号
        creditAdd.put("creditsShopName", ShopDetails.get("goodsName")); // 商品名
        creditAdd.put("creditsShopSn", ShopDetails.get("goodsSn")); // 商品编号
        creditAdd.put("creditsNum", ShopDetails.get("creditPrice")); // 消耗积分
        creditAdd.put("accountCredits", tdMoney); // 账户剩余积分 目前积分 - 消耗积分
        // 生成消耗积分的记录
        creditAdd.put("creditsShopOrderSn", DataSn);
        getCredits.saveExpend(creditAdd);
    }

    /**
     * @param map
     * @description: 撤销订单
     * @return: com.example.common.entity.Result
     * @author: xxx
     * @time: 2021/5/06 09:30
     */
    @RequestMapping("cancleOrder")
    public Result cancleOrder(@RequestBody Map<String, Object> map) throws Exception {
        // 当前方法加锁 防止多个接口同时调用
        lock.lock();
        try {
            // 1. 查询订单状态是否为1 并且记分表中没有退货的记录
            Map<String, Object> orderMap = new HashMap();
            orderMap.put("id", map.get("id"));
            Map<String, Object> orderData = service.getById(orderMap);
            Integer added = (Integer) orderData.get("added");
            if (added == 1) {
                creditsOrder.returnCreditsAndCc(map, orderData);
                return ResultUtil.success();
            } else {
                return ResultUtil.error(-500, "当前状态无法撤销");
            }
        } catch (Exception e) {
            return ResultUtil.error(-500, "撤销失败");
        } finally {
            // 解锁
            lock.unlock();
        }
    }

    // 撤销兑换具体方法(事务模式)
    @Transactional(rollbackFor = Exception.class)
    public void returnCreditsAndCc(Map<String, Object> map, Map<String, Object> orderData) {
        // 获取用户信息
        Map<String, Object> userMap = new HashMap();
        userMap.put("id", TokenTool.getUserId());
        Map<String, Object> userInfo = userService.getById(userMap);
        // 获取用户积分
        Map<String, Object> UserCredits = getCredits.getMyCredits(userMap);
        // 1. 撤销订单
        map.put("added", 6);
        service.update(map);
        // 2. 查询商品信息  更新商品库存
        // 2.1 查询商品信息
        Map<String, Object> shopdetails = new HashMap();
        shopdetails.put("id", orderData.get("shopId"));
        Map<String, Object> ShopDetails = creditsShopsService.getById(shopdetails);
        // 2.2 更新商品库存
        Integer surpusStock = (Integer) ShopDetails.get("surplusStock");
        Map<String, Object> shopkc = new HashMap();
        surpusStock = surpusStock + 1;
        shopkc.put("id", ShopDetails.get("id"));
        shopkc.put("surplusStock", surpusStock);
        creditsShopsService.update(shopkc);
        // 3. 返还积分
        // 计算剩余积分 账户积分+返还积分
        BigDecimal totalC = new BigDecimal(Double.valueOf(UserCredits.get("total").toString()));  // 账户目前可用积分 total
        BigDecimal gCredit = new BigDecimal(Double.valueOf(orderData.get("shopCreditsPrice").toString()));// 此单返还积分金额
        BigDecimal tdMoney = totalC.add(gCredit).setScale(2, BigDecimal.ROUND_HALF_UP);// 加法四舍五入保留两位小数
        // 插入数据
        Map<String, Object> creditAdd = new HashMap();
        creditAdd.put("id", IDTool.getUUID32()); // 数据id
        creditAdd.put("userId", userInfo.get("id")); // 用户id
        creditAdd.put("userPhone", userInfo.get("name")); // 用户手机号
        creditAdd.put("userName", userInfo.get("nikeName")); // 用户手机号
        creditAdd.put("creditsShopName", orderData.get("shopName")); // 商品名
        creditAdd.put("creditsShopSn", orderData.get("orderSn")); // 商品编号
        creditAdd.put("getCredits", orderData.get("shopCreditsPrice")); // 返还积分
        creditAdd.put("creditsShopOrderSn", orderData.get("orderSn")); // 订单编号
        creditAdd.put("accountCredits", tdMoney); // 账户剩余积分 目前积分 + 返还积分
        getCredits.saveRefund(creditAdd);
    }

    /**
     * @param map
     * @description: 修改
     * @return: com.example.common.entity.Result
     * @author: xxx
     * @time: 2021/5/06 09:30
     */
    @RequestMapping("update")
    public Result update(@RequestBody Map<String, Object> map) {
        service.update(map);
        return ResultUtil.success();
    }

    /**
     * @param map
     * @description: 删除
     * @return: com.example.common.entity.Result
     * @author: xxx
     * @time: 2021/5/06 09:30
     */
    @RequestMapping("delete")
    public Result delete(@RequestBody Map<String, Object> map) {
        service.delete(map);
        return ResultUtil.success();
    }
}
